#pragma once
#include <mutex>
#include <queue>
#include <condition_variable>

namespace lakes {
    
    template <typename T>
    class TaskQueue {
    public:
        T GetTask() {         
            std::lock_guard<std::mutex> lg(m_TaskQueueMutex);
            T task;
            if (!m_queueTask.empty()) {
                task = m_queueTask.front();
                m_queueTask.pop();
            }
            return task;
        }

        void putTask(T task) {
            std::lock_guard<std::mutex> lg(m_TaskQueueMutex);
            m_queueTask.push(task);
            signalOneConsumer();
        }

        int getTaskQueueNum() {
            std::lock_guard<std::mutex> lg(m_TaskQueueMutex);
            return static_cast<int>(m_queueTask.size());
        }

        void waitProducerSignal() {
            std::unique_lock<std::mutex> uniqueLock(m_TaskQueueMutex);  
            m_isEmptyCond.wait(uniqueLock);
        }

        void signalOneConsumer() {
            m_isEmptyCond.notify_one();
        }

        void signalAllConsumer() {
            m_isEmptyCond.notify_all();
        }

    private:
        std::mutex m_TaskQueueMutex;
        std::condition_variable m_isEmptyCond;       
        std::queue<T> m_queueTask;
    };

} // namespace lakes


